﻿using System;
using System.Collections;
using System.Text;
using System.Xml;
using System.Web;
using System.IO;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{
	
	class XSNViewFormatStyleWorker
	{

		private static string XDocRulePrefix = ".xdoc {";
		
		public static void formatStyle(HttpContext httpContext, View view)
		{
			XmlElement root = view.Doc.DocumentElement;

			//CID 0063 //2008.07.24 //Begin
			if( linkCSS( httpContext, view, root ) )
			{
				return;
			}
			else
			{
				//CID 0093 //2008.08.20 //Begin
				formatH5( view, root );
				//CID 0093 //2008.08.20 //End

				formatControlStyle( view, root );
				formatLanguageStyle( view, root );
				formatThemeStyle( view, root );

				processMarginLeft( view, root );
			}
			//CID 0063 //2008.07.24 //End
		}

		//CID 0093 //2008.08.20 //Begin
		public static void formatH5(View view, XmlElement root)
		{
			string h5Color = null;

			string themeStyleFilter = "//style[@themeStyle]";
			XmlElement themeStyleElement = (XmlElement) DOMUtil.selectANode(root, themeStyleFilter, view.NsResolver);
			if (themeStyleElement != null)
			{
				XmlNodeList nodeList = themeStyleElement.ChildNodes;
				foreach (XmlNode node in nodeList)
				{
					if (node is XmlText)
					{
						XmlText text = (XmlText) node;
						string style = text.Value;

						int h5Begin = style.IndexOf( "H5 {" );
						if( h5Begin >= 0 )
						{
							int colorIndex = style.IndexOf( "COLOR: ", h5Begin );
							int endIndex = style.IndexOf( "}", h5Begin );
							if( colorIndex < endIndex )
							{
								colorIndex = colorIndex + "COLOR: ".Length;
								if( colorIndex > 0 && colorIndex < (style.Length - 7) )
								{
									h5Color = style.Substring( colorIndex, 7 );
									break;
								}
							}
						}
					}
				}
			}

			if( h5Color != null )
			{
				string tableEditorStyleFilter = "//style[@tableEditor]";
				XmlElement tableEditorStyleElement = (XmlElement) DOMUtil.selectANode(root, tableEditorStyleFilter, view.NsResolver);
				if (tableEditorStyleElement != null)
				{
					XmlNodeList nodeList = tableEditorStyleElement.ChildNodes;
					foreach (XmlNode node in nodeList)
					{
						if (node is XmlText)
						{
							XmlText text = (XmlText) node;
							string style = text.Value;

							int tdBegin = style.IndexOf( "TABLE.msoUcTable TD {" );
							if( tdBegin >= 0 )
							{
								style = style.Replace( "BORDER-RIGHT: 1pt solid; BORDER-TOP: 1pt solid; BORDER-LEFT: 1pt solid; BORDER-BOTTOM: 1pt solid",
									"BORDER-RIGHT: 1pt solid " + h5Color + "; BORDER-TOP: 1pt solid " + h5Color + "; BORDER-LEFT: 1pt solid " + h5Color + "; BORDER-BOTTOM: 1pt solid " + h5Color);
								text.Value = style;
							}
						}
					}
				}
			}
		}
		//CID 0093 //2008.08.20 //End

		//CID 0041 //2008.07.09 //Begin
		private static bool linkCSS( HttpContext httpContext, View view, XmlElement root )
		{
			string linkCss = ConfigUtil.LinkCSS();
			if( linkCss != null )
			{
				//CID 0091 //2008.08.13 //Begin
				if( linkCss.StartsWith( "~" ) )
				{
					linkCss = linkCss.Replace( "~", PathUtil.getAppPath(httpContext) );
				}
				//CID 0091 //2008.08.13 //End
				string path = httpContext.Request.MapPath( linkCss );
				//CID 0126 //2008.09.28 //Begin
				FileStream input = File.OpenRead( path );
				//CID 0126 //2008.09.28 //End	
				byte[] content = new byte[ (int)input.Length ];
				input.Read( content, 0, content.Length );
				input.Close();

				string css = System.Text.Encoding.UTF8.GetString( content );

				XmlElement parentNode = null;
				XmlNodeList styleNodeList = DOMUtil.selectNodes( root, "//style", 0, view.NsResolver );
				foreach( XmlElement styleElement in styleNodeList )
				{
					parentNode = styleElement.ParentNode as XmlElement;
					styleElement.ParentNode.RemoveChild( styleElement );
				}
				if( parentNode != null )
				{
					XmlElement styleElement = view.Doc.CreateElement( "style" );
					styleElement.SetAttribute( "linkCSS", "true" );

					//CID 0063 //2008.07.24 //Begin
					if( ConfigUtil.UnoverridableStyles() )
					{
						css = convertTagRule2AttributeStyle( root, css, "SELECT {", "select" );
						css = convertTagRule2AttributeStyle( root, css, "TABLE {", "table" );
						css = convertTagRule2AttributeStyle( root, css, "TD {", "td" );
						css = convertTagRule2AttributeStyle( root, css, "TH {", "th" );
						css = convertTagRule2AttributeStyle( root, css, "P {", "p" );
						css = convertTagRule2AttributeStyle( root, css, "H1 {", "h1" );
						css = convertTagRule2AttributeStyle( root, css, "H2 {", "h2" );
						css = convertTagRule2AttributeStyle( root, css, "H3 {", "h3" );
						css = convertTagRule2AttributeStyle( root, css, "H4 {", "h4" );
						css = convertTagRule2AttributeStyle( root, css, "H5 {", "h5" );
						css = convertTagRule2AttributeStyle( root, css, "H6 {", "h6" );
					}
					//CID 0063 //2008.07.24 //End

					styleElement.InnerText = css;
					parentNode.AppendChild( styleElement );

					//CID 0041 //2008.07.09 //Begin
					processMarginLeft( view, root );
					//CID 0041 //2008.07.09 //End
				}
				//LinkCSS应当是格式好了的CSS.
				return true;
			}
			else
			{
				return false;
			}
		}
		//CID 0041 //2008.07.09 //End

		//CID 0041 //2008.07.09 //Begin
		private static void processMarginLeft( View view, XmlElement root )
		{
			string marginLeft = ConfigUtil.FormViewMarginLeft();
			if( marginLeft != null )
			{
				string styleFilter = "//style";
				XmlNodeList styleElementNodeList = DOMUtil.selectNodes(root, styleFilter, 0, view.NsResolver);
				if( styleElementNodeList.Count > 0 )
				{
					XmlElement lastStyleElement = (XmlElement)styleElementNodeList[ styleElementNodeList.Count - 1 ];
					XmlText styleText = view.Doc.CreateTextNode( ".xdoc { margin-left:" + marginLeft + "; }"  );
					lastStyleElement.AppendChild( styleText );
				}
			}
		}
		//CID 0041 //2008.07.09 //End

		private static void formatThemeStyle( View view, XmlElement root )
		{
			string themeStyleFilter = "//style[@themeStyle]";
			XmlElement themeStyleElement = (XmlElement) DOMUtil.selectANode(root, themeStyleFilter, view.NsResolver);
			if (themeStyleElement != null)
			{
				XmlNodeList nodeList = themeStyleElement.ChildNodes;
				foreach (XmlNode node in nodeList)
				{
					if (node is XmlText)
					{
						XmlText text = (XmlText) node;
						string style = text.Value;
						
						style = formatBodyStyleRule( style );

						//CID 0055 //2008.07.22 //Begin
						if( ConfigUtil.UnoverridableStyles() )
						{
							style = convertTagRule2AttributeStyle( root, style, "TABLE {", "table" );
							style = convertTagRule2AttributeStyle( root, style, "TD {", "td" );
							style = convertTagRule2AttributeStyle( root, style, "TH {", "th" );
							style = convertTagRule2AttributeStyle( root, style, "P {", "p" );
							style = convertTagRule2AttributeStyle( root, style, "H1 {", "h1" );
							style = convertTagRule2AttributeStyle( root, style, "H2 {", "h2" );
							style = convertTagRule2AttributeStyle( root, style, "H3 {", "h3" );
							style = convertTagRule2AttributeStyle( root, style, "H4 {", "h4" );
							style = convertTagRule2AttributeStyle( root, style, "H5 {", "h5" );
							style = convertTagRule2AttributeStyle( root, style, "H6 {", "h6" );
						}
						//CID 0055 //2008.07.22 //End

						text.Value = style;
					}
				}
			}
		}

		private static void formatLanguageStyle( View view, XmlElement root )
		{
			string languageStyleFilter = "//style[@languageStyle='languageStyle']";
			XmlElement languageStyleElement = (XmlElement) DOMUtil.selectANode(root, languageStyleFilter, view.NsResolver);
			if (languageStyleElement != null)
			{
				XmlNodeList nodeList = languageStyleElement.ChildNodes;
				foreach (XmlNode node in nodeList)
				{
					if (node is XmlText)
					{
						XmlText text = (XmlText) node;
						string style = text.Value;
						int beginIndex = -1;
						
						style = formatBodyStyleRule( style );
						//CID 0068 //2008.07.27 //Begin
						style = addTextStylesInheritedXDocStyle( style );
						//CID 0068 //2008.07.27 //End
						
						beginIndex = style.IndexOf(".optionalPlaceholder");
						if (beginIndex >= 0)
						{
							int index = style.IndexOf("}", beginIndex);
							if (index > 0)
							{
								style = style.Insert(index, ";cursor:pointer;cursor:hand;");
							}
							index = style.IndexOf("PADDING-LEFT: 20px;", beginIndex);
							if (index > 0)
							{
								style = StringUtil.replace( style , index , "PADDING-LEFT: 20px;".Length ,  "PADDING-LEFT: 3px;" );
							}
						}

						//CID 0055 //2008.07.22 //Begin
						if( ConfigUtil.UnoverridableStyles() )
						{
							//CID 0066 //2008.07.27 //Begin
							style = addTdStyleInheritedTableStyle( style );
							//CID 0066 //2008.07.27 //End

							style = convertTagRule2AttributeStyle( root, style, "TABLE {", "table" );
							style = convertTagRule2AttributeStyle( root, style, "TD {", "td" );
							style = convertTagRule2AttributeStyle( root, style, "SELECT {", "select" );
						}
						//CID 0055 //2008.07.22 //End

						text.Value = style;
					}
				}
			}
		}

		//CID 0055 //2008.07.22 //Begin
		private static string convertTagRule2AttributeStyle( XmlElement root, string style, string start, string tagName )
		{
			//CID 0063 //2008.07.24 //Begin
			//为支持LinkCSS,LinkCSS中一般包含多个重复的Tag Rule,比如多个table{}.
			int startIndex = 0;
			int beginIndex = style.IndexOf(start, startIndex);
			while( beginIndex >= 0 )
			{
				if( beginIndex > 1 )
				{
					//判断是否是TABLE.xdLayout TD
					bool isTag = true;
					int lastBracketIndex = style.LastIndexOf( "}", beginIndex );
					if( lastBracketIndex > 0 )
					{
						string prefix = style.Substring( lastBracketIndex + 1, beginIndex - lastBracketIndex - 1 ).Trim();
						//开始和前面的}之间无内容
						if( prefix.Length > 0 )
						{
							isTag = false;
						}
					}
					else
					{
						string prefix = style.Substring( 0, beginIndex ).Trim();
						//开始到最前之间无内容.
						if( prefix.Length > 0 )
						{
							isTag = false;
						}
					}
					if( !isTag )
					{
						startIndex = beginIndex + start.Length;
						beginIndex = style.IndexOf(start, startIndex);
						continue;
					}
				}
				//CID 0063 //2008.07.24 //End
				int endIndex = style.IndexOf( "}", beginIndex );
				if( endIndex > beginIndex )
				{
					string tagStyle = style.Substring( beginIndex + start.Length, endIndex - beginIndex - start.Length ).Replace( "\r\n", "" ).Replace( "\n", "" ).Trim();
					if( !tagStyle.EndsWith( ";" ) )
					{
						tagStyle = tagStyle + ";";
					}
					style = StringUtil.replace( style , beginIndex , endIndex - beginIndex + 1,  "" );
					
					XmlNodeList tableElementList = root.SelectNodes( "//" + tagName );
					foreach( XmlElement tableElement in tableElementList )
					{
						XmlAttribute styleAttr = tableElement.GetAttributeNode( "style" );
						if( styleAttr != null )
						{
							styleAttr.Value = tagStyle + styleAttr.Value;
						}
						else
						{
							tableElement.SetAttribute( "style", tagStyle );
						}
					}

					startIndex = endIndex;
					beginIndex = style.IndexOf(start);
				}
				else
				{
					break;
				}
			}
			return style;
		}
		//CID 0055 //2008.07.22 //End

		private static void formatControlStyle( View view, XmlElement root )
		{
			string controlStyleFilter = "//style[@controlStyle='controlStyle']";
			XmlElement controlStyleElement = (XmlElement) DOMUtil.selectANode(root, controlStyleFilter, view.NsResolver);
			if (controlStyleElement != null)
			{
				XmlNodeList nodeList = controlStyleElement.ChildNodes;
				foreach (XmlNode node in nodeList)
				{
					if (node is XmlText)
					{
						XmlText text = (XmlText) node;
						string style = text.Value;
						int beginIndex = -1;

						//CID 0055 //2008.07.19 //Begin
						style = formatBodyStyleRule( style );
						//CID 0055 //2008.07.19 //End
						
						beginIndex = style.IndexOf(".xdListItem");
						if (beginIndex >= 0) 
						{
							int index = style.IndexOf("}", beginIndex);
							if (index > 0) 
							{
								style = style.Insert(index, ";border:0px;");
							}
						}

						beginIndex = style.IndexOf(".xdDTText{");
						if (beginIndex >= 0)
						{
							int index = style.IndexOf("}", beginIndex);
							if (index > 0)
							{
								style = style.Insert(index, ";border:0px;");
							}
						}
						
						style = style + "@media print{ .xdDTButton {display:none;} .xdDTButtonRTL {display:none;} .hiddenButton{display:none;} .optionalPlaceholder{display:none;} }";
						
						text.Value = style;
					}
				}
			}
			
		}

		//CID 0055 //2008.07.19 //Begin
		private static string formatBodyStyleRule( string style )
		{
			int begin1Index = -1;
			int begin2Index = -1;

			begin1Index = style.IndexOf("BODY{");
			if( begin1Index < 0 )
			{
				begin2Index = style.IndexOf("BODY {");
			}
			while (begin1Index >= 0 || begin2Index >= 0)
			{
				if( begin1Index >= 0 )
				{
					style = StringUtil.replace( style , begin1Index , "BODY{".Length , XDocRulePrefix );
				}
				if( begin2Index >= 0 )
				{
					style = StringUtil.replace( style , begin2Index , "BODY {".Length , XDocRulePrefix );
				}

				//Loop the next "BODY" style rule.
				begin1Index = style.IndexOf("BODY{");
				if( begin1Index < 0 )
				{
					begin2Index = style.IndexOf("BODY {");
				}
			}
			
			return style;
		}
		//CID 0055 //2008.07.19 //End

		//CID 0068 //2008.07.27 //Begin
		private static string addTextStylesInheritedXDocStyle( string style )
		{
			int beginIndex = style.IndexOf( ".xdoc {" );
			if( beginIndex >= 0 )
			{
				int endIndex = style.IndexOf( "}", beginIndex );
				if( endIndex > 0 )
				{
					string xdocStyle = style.Substring( beginIndex + XDocRulePrefix.Length, endIndex - beginIndex - XDocRulePrefix.Length );
					style = style + " .xdTextBox {" + xdocStyle + "} .xdRichTextBox {" + xdocStyle + "}" + " .xdDTText {" + xdocStyle + "}";
				}
			}
			return style;
		}
		//CID 0068 //2008.07.27 //End

		//CID 0066 //2008.07.27 //Begin
		private static string addTdStyleInheritedTableStyle( string style )
		{
			string TablePrefix = "TABLE {";
			int beginIndex = style.IndexOf( TablePrefix );
			if( beginIndex >= 0 )
			{
				int endIndex = style.IndexOf( "}", beginIndex );
				if( endIndex > 0 )
				{
					string xdocStyle = style.Substring( beginIndex + TablePrefix.Length, endIndex - beginIndex - TablePrefix.Length );
					style = style + " TD {" + xdocStyle + "}";
				}
			}
			return style;
		}
		//CID 0066 //2008.07.27 //End
	}
}